﻿#include "LineChartTracer.h"
#include "Curve2DPlotor.h"
#include <QDebug>
#include "IdaWidgetHelper.h"
#include "PolarGraph.h"
#include "Curve2DPlotor.h"
#include "InfomationCurve2DBasical.h"
#include "BaseModule/GlobalHelper.h"
#include "BaseWidget/InternalWindowFrameless.h"
#include "DataManager/WindowTotalData.h"

#include "BaseWidget/IWidgetSignal.h"

namespace pst
{
    // class ItemLine : public QCPItemLine
    //{
    // public:
    //     void setPolarGraph(QCPPolarGraph* graph)
    //     {
    //         m_polarGrah = graph;
    //     }

    //    QCPPolarGraph* getPolarGraph() const
    //    {
    //        return m_polarGrah;
    //    }

    //    void draw(QCPPainter* painter) override
    //    {
    //        QCPVector2D startVec(start->pixelPosition());
    //        QCPVector2D endVec(end->pixelPosition());
    //        if (qFuzzyIsNull((startVec - endVec).lengthSquared()))
    //            return;
    //        // get visible segment of straight line inside clipRect:
    //        int clipPad = int(qMax(mHead.boundingDistance(), mTail.boundingDistance()));
    //        clipPad = qMax(clipPad, qCeil(mainPen().widthF()));
    //        QLineF line = getRectClippedLine(startVec, endVec, clipRect().adjusted(-clipPad, -clipPad, clipPad, clipPad));
    //        // paint visible segment, if existent:

    //        if (m_polarGrah)
    //        {
    //            auto valueAxis = m_polarGrah->valueAxis();
    //            if (valueAxis)
    //            {
    //                QCPRange valueRange = m_polarGrah->valueAxis()->range();
    //            }
    //
    //        }

    //        if (!line.isNull())
    //        {
    //            painter->setPen(mainPen());
    //            painter->drawLine(line);
    //            painter->setBrush(Qt::SolidPattern);
    //            if (mTail.style() != QCPLineEnding::esNone)
    //                mTail.draw(painter, startVec, startVec - endVec);
    //            if (mHead.style() != QCPLineEnding::esNone)
    //                mHead.draw(painter, endVec, endVec - startVec);
    //        }
    //    }
    // protected:
    //    QCPPolarGraph* m_polarGrah{ nullptr };
    //};

    LineChartTracer::LineChartTracer(QCustomPlot* parentPlot) : QCPItemTracer(parentPlot)
    {
        m_isOnlyShowTracer = false;
        m_value = std::numeric_limits<double>::quiet_NaN();
        m_layerable = nullptr;
        this->setLayer("overlay");
        this->setInterpolating(true);
        this->setStyle(QCPItemTracer::tsCircle);
        this->setPen(QPen(Qt::red));
        // this->setBrush(Qt::red);
        this->setSize(6);
        m_style2D_TracerProperty = new Style2D_TracerProperty(this);
        m_label = new QCPItemText(parentPlot);
        m_label->setLayer("overlay");
        m_label->position->setParentAnchor(this->position);
        m_label->position->setCoords(0, -25);
        m_label->setPen(QPen(Qt::black));
        m_label->setBrush(Qt::white);
        m_label->setSelectedPen(QPen(Qt::blue));
        m_label->setSelectedBrush(Qt::white);
        m_label->setPadding({5, 5, 5, 5});
        m_arrow = new QCPItemLine(parentPlot);
        m_arrow->setLayer("overlay");
        m_arrow->start->setParentAnchor(m_label->bottom);
        m_arrow->end->setParentAnchor(this->position);
        m_arrow->setHead(QCPLineEnding::esLineArrow);
        connect(this, &LineChartTracer::selectionChanged, this, [this](bool selected)
            {
                slot_selectChange(selected);
                QString _pyCode = QString("PostProcessing.lineChartLineChartTracerSelectChange(%1,%2)").arg(m_tracerIndex).arg(selected);
                emit IBaseSignalInstance->signal_execPYCode(QStringList{_pyCode}, true, false); 
            });
        connect(m_label, &QCPItemText::selectionChanged, this, [this](bool selected)
                {
                slot_selectChange(selected);
                QString _pyCode = QString("PostProcessing.lineChartLineChartTracerSelectChange(%1,%2)").arg(m_tracerIndex).arg(selected);
                emit IBaseSignalInstance->signal_execPYCode(QStringList{_pyCode}, true, false); });
        connect(m_arrow, &QCPItemLine::selectionChanged, this, [this](bool selected)
                {
                slot_selectChange(selected);
                QString _pyCode = QString("PostProcessing.lineChartLineChartTracerSelectChange(%1,%2)").arg(m_tracerIndex).arg(selected);
                emit IBaseSignalInstance->signal_execPYCode(QStringList{_pyCode}, true, false); 
            });
        connect(IWidgetSignalInstance, &BaseWidget::IWidgetSignal::signal_lineChartLineChartTracerSelectChange, this, [this, parentPlot](int id, bool selected)
                {
            if(!parentPlot->isVisible()) return;
            if (id != m_tracerIndex)
                return;
            slot_selectChange(selected); 
                parentPlot->replot();
        });
    }

    LineChartTracer::~LineChartTracer()
    {
        auto parentPlot = qobject_cast<QCustomPlot*>(this->parent());
        if (parentPlot->hasItem(m_arrow))
        {
            parentPlot->removeItem(m_arrow);
        }
        if (parentPlot->hasItem(m_label))
        {
            parentPlot->removeItem(m_label);
        }
    }

    QDomElement& LineChartTracer::writeToProjectFile(QDomDocument* doc, QDomElement* element, GraphType type, bool isdiso)
    {
        QDomElement _LineChartTracerDataRoot = doc->createElement("LineChartTracer");
        QDomAttr idattr = doc->createAttribute("ID");
        idattr.setValue(QString::number(1));
        _LineChartTracerDataRoot.setAttributeNode(idattr);
        QDomAttr typeattr = doc->createAttribute("TracerType");
        typeattr.setValue("LineChart");
        _LineChartTracerDataRoot.setAttributeNode(typeattr);

        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "TracerIndex", QString::number(m_tracerIndex));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "IsOnlyShowTracer", QString::number(m_isOnlyShowTracer));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "Value", QString::number(m_value));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "CurveInfoID", QString::number(m_curveInfoID));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "Name", m_name);
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "GraphAngle", QString::number(m_graphAngle));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "PolarAngleCoord", QString::number(m_polarAngleCoord));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "PolarRadiusCoord", QString::number(m_polarRadiusCoord));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "ShowLabelAndArrow", QString::number(m_showLabelAndArrow));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "IsMeasurementConditionsSatisfied", QString::number(m_isMeasurementConditionsSatisfied));

        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "InternalPositionX", QString::number(this->position->coords().x()));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "InternalPositionY", QString::number(this->position->coords().y()));
        GlobalHelperInstance->createDomElement(doc, &_LineChartTracerDataRoot, "InternalValue", QString::number(this->GetValue()));


        element->appendChild(_LineChartTracerDataRoot);
        m_style2D_TracerProperty->writeToProjectFile(doc, &_LineChartTracerDataRoot, isdiso);

        return _LineChartTracerDataRoot;
    }

    void LineChartTracer::readFromProjectFile(QDomElement* element, GraphType type, bool isdiso)
    {
        int tracerID = element->attribute("ID").toInt();
        auto _TracerIndexNodeList = element->elementsByTagName("TracerIndex");
        m_tracerIndex = _TracerIndexNodeList.item(0).toElement().text().toInt();
        auto _IsOnlyShowTracerNodeList = element->elementsByTagName("IsOnlyShowTracer");
        m_isOnlyShowTracer = (bool)_IsOnlyShowTracerNodeList.item(0).toElement().text().toInt();
        m_value = element->elementsByTagName("Value").item(0).toElement().text().toDouble();
        auto _name = element->elementsByTagName("Name").item(0).toElement().text();
        this->SetName(_name);
        m_curveInfoID = element->elementsByTagName("CurveInfoID").item(0).toElement().text().toInt();
        auto _info = WindowTotalDataInstance->getInfomationCurve2DBasicalByID(m_curveInfoID);
        if (type == GraphType::TwoDLineChart)
        {
            QCPGraph* graph = qobject_cast<QCPGraph*>(_info->getCurveLineAddress());
            this->SetLayerable(graph);
        }
        else if (type == GraphType::PolarGraph)
        {
            QCPPolarGraph* graph = qobject_cast<QCPPolarGraph*>(_info->getCurveLineAddress());
            this->SetLayerable(graph);
        }
        else if (type == GraphType::TwoDHeatMap)
        {
            QCPColorMap* graph = qobject_cast<QCPColorMap*>(_info->getCurveLineAddress());
            this->SetLayerable(graph);
        }
        m_graphAngle = element->elementsByTagName("GraphAngle").item(0).toElement().text().toDouble();
        m_polarAngleCoord = element->elementsByTagName("PolarAngleCoord").item(0).toElement().text().toDouble();
        m_polarRadiusCoord = element->elementsByTagName("PolarRadiusCoord").item(0).toElement().text().toDouble();
        m_showLabelAndArrow = (bool)element->elementsByTagName("ShowLabelAndArrow").item(0).toElement().text().toInt();
        m_isMeasurementConditionsSatisfied = (bool)element->elementsByTagName("IsMeasurementConditionsSatisfied").item(0).toElement().text().toInt();
        auto _positionX= element->elementsByTagName("InternalPositionX").item(0).toElement().text().toDouble();
        auto _positionY = element->elementsByTagName("InternalPositionY").item(0).toElement().text().toDouble();
        this->position->setCoords(_positionX, _positionY);
        m_value = element->elementsByTagName("InternalValue").item(0).toElement().text().toDouble();

        m_style2D_TracerProperty->readFromProjectFile(&element->elementsByTagName("Style2D_TracerProperty").item(0).toElement(), isdiso);
    }

    void LineChartTracer::mousePressEvent(QMouseEvent* event, const QVariant& details)
    {
        Q_UNUSED(details)
        if (this->graph() != nullptr)
        {
            event->accept();
            return;
        }

        Curve2DPlotor* curve2DPlotor = qobject_cast<Curve2DPlotor*>(this->parent());
        if (curve2DPlotor)
        {
            PolarAxisAngular* polarAxisAngular = curve2DPlotor->getPolarAxisAngular();
            if (polarAxisAngular && !polarAxisAngular->getGraphList().isEmpty())
            {
                event->accept();
                return;
            }
        }

        event->ignore();
    }

    void LineChartTracer::mouseMoveEvent(QMouseEvent* event, const QPointF& startPos)
    {
        auto parentPlot = qobject_cast<QCustomPlot*>(this->parent());

        if (m_polarGraph)
        {
            auto polarAxisAngular = m_polarGraph->keyAxis();
            if (polarAxisAngular)
            {
                double angle = 0.0;
                double radius = 0.0;
                polarAxisAngular->pixelToCoord(event->pos(), angle, radius);
                setGraphAngle(angle);
            }
        }
        else
        {
            this->setGraphKey(parentPlot->xAxis->pixelToCoord(event->pos().x()));
        }

        parentPlot->replot();
    }

    void LineChartTracer::slot_selectChange(bool selected)
    {
        this->blockSignals(true);
        m_label->blockSignals(true);
        m_arrow->blockSignals(true);
        this->setSelected(selected);
        m_label->setSelected(selected);
        m_arrow->setSelected(selected);
        this->blockSignals(false);
        m_label->blockSignals(false);
        m_arrow->blockSignals(false);
    }

    void LineChartTracer::updatePositionOnPolar()
    {
        auto lmd_setCoords = [this](double key, double value)
        {
            m_polarAngleCoord = key;
            m_polarRadiusCoord = value;
            position->setPixelPosition(m_polarGraph->coordsToPixels(key, value));
        };

        // 定义一个临时 lambda 函数，用于归一化角度到 [-180, 180]
        auto normalizeAngle = [](double angle) -> double
        {
            // 先使用 std::fmod 计算 angle 除以 360 后的余数
            double ret = std::fmod(angle, 360.0);
            // 注意：std::fmod 对于负数的余数保留负号
            // 如果余数大于 180，则减去 360，使其进入 [-180, 180] 内
            if (ret > 180.0)
            {
                ret -= 360.0;
            }
            // 如果余数小于 -180，则加上 360
            else if (ret < -180.0)
            {
                ret += 360.0;
            }
            return ret;
        };

        if (std::isnan(m_graphAngle))
        {
            lmd_setCoords(position->key(), position->value());
            return;
        }

        if (m_polarGraph->data()->isEmpty())
        {
            return;
        }
        else if (m_polarGraph->data()->size() == 1)
        {
            QCPGraphDataContainer::const_iterator it = m_polarGraph->data()->constBegin();
            lmd_setCoords(normalizeAngle(it->key), it->value);
            return;
        }

        QCPGraphDataContainer::const_iterator first = m_polarGraph->data()->constBegin();
        QCPGraphDataContainer::const_iterator last = m_polarGraph->data()->constEnd() - 1;

        // if (m_graphAngle < first->key)
        //{
        //     lmd_setCoords(first->key, first->value);
        // }
        // else if (m_graphAngle > last->key)
        //{
        //     lmd_setCoords(last->key, last->value);
        // }
        // else
        {
            // QCPGraphDataContainer::const_iterator it = m_polarGraph->data()->findBegin(m_graphAngle);
            for (auto iter = m_polarGraph->data()->begin(); iter != m_polarGraph->data()->end(); ++iter)
            {
                auto it = iter;
                QCPGraphDataContainer::const_iterator prevIt = it;
                ++it;
                if (it != m_polarGraph->data()->constEnd())
                {
                    double p = normalizeAngle(prevIt->key);
                    double n = normalizeAngle(it->key);
                    if (p > 0 && n < 0)
                    {
                        p -= 360.0;
                    }
                    QCPRange a(p, n);
                    if (!a.contains(m_graphAngle))
                    {
                        continue;
                    }
                    double slope = 0;
                    if (!qFuzzyCompare(double(it->key), double(prevIt->key)))
                    {
                        slope = (it->value - prevIt->value) / (it->key - prevIt->key);
                    }
                    lmd_setCoords(m_graphAngle, (m_graphAngle - p) * slope + prevIt->value);
                    break;
                }
            }
        }
    }

    void LineChartTracer::setStyle2DTracerProperty(Style2D_TracerProperty* style2D_TracerProperty)
    {
        m_style2D_TracerProperty = style2D_TracerProperty;
    }
    Style2D_TracerProperty* LineChartTracer::getStyle2DTracerProperty()
    {
        return m_style2D_TracerProperty;
    }

    void LineChartTracer::draw(QCPPainter* painter)
    {
        if (m_polarGraph)
        {
            updatePositionOnPolar();
            QCPRange range = m_polarGraph->valueAxis()->range();
            if (m_polarRadiusCoord < range.lower || m_polarRadiusCoord > range.upper)
            {
                if (m_showLabelAndArrow)
                {
                    m_label->setVisible(false);
                    m_arrow->setVisible(false);
                }
                return;
            }
            else
            {
                if (m_showLabelAndArrow)
                {
                    m_label->setVisible(true);
                    m_arrow->setVisible(true);
                }
            }
        }
        QCPItemTracer::draw(painter);
    }

    BeamBandwidthTracer::BeamBandwidthTracer(QCustomPlot* parentPlot) : LineChartTracer(parentPlot)
    {
        m_standingWwaveValue = std::numeric_limits<double>::quiet_NaN();
        m_indicator = new QCPItemLine(parentPlot);
        m_indicator->setLayer("overlay");
        m_indicator->setHead(QCPLineEnding::esLineArrow);
        m_indicator->setTail(QCPLineEnding::esLineArrow);
        connect(m_indicator, &QCPItemLine::selectionChanged, this, &LineChartTracer::slot_selectChange);
    }

    BeamBandwidthTracer::~BeamBandwidthTracer()
    {
        auto parentPlot = qobject_cast<QCustomPlot*>(this->parent());
        if (parentPlot->hasItem(m_indicator))
        {
            parentPlot->removeItem(m_indicator);
        }
    }

    QDomElement& BeamBandwidthTracer::writeToProjectFile(QDomDocument* doc, QDomElement* element, GraphType type, bool isdiso)
    {
        QDomElement _BeamBandwidthTracerDataRoot = doc->createElement("LineChartTracer");
        QDomAttr idattr = doc->createAttribute("ID");
        idattr.setValue(QString::number(1));
        _BeamBandwidthTracerDataRoot.setAttributeNode(idattr);
        QDomAttr typeattr = doc->createAttribute("TracerType");
        typeattr.setValue("BeamBandwidth");
        _BeamBandwidthTracerDataRoot.setAttributeNode(typeattr);

        GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "StandingWwaveValue", QString::number(m_standingWwaveValue));
        GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "Name", this->GetName());
        GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "CurveInfoID", QString::number(m_curveInfoID));
        if (type == GraphType::TwoDLineChart)
        {
            GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "InternalGraphName", qobject_cast<QCPGraph*>(this->GetLayerable())->name());
        }
        else if (type == GraphType::PolarGraph)
        {
            GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "InternalGraphName", qobject_cast<QCPPolarGraph*>(this->GetLayerable())->name());
        }            
        if (this->GetName() == "半功率波束带宽" || this->GetName() == "驻波带宽")
        {
            auto indeicator = qobject_cast<BeamBandwidthTracer*>(this)->GetIndicator();
            GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "InternalindeicatorStartX", QString::number(indeicator->start->coords().x()));
            GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "InternalindeicatorEndX", QString::number(indeicator->end->coords().x()));
        }
        else
        {
            GlobalHelperInstance->createDomElement(doc, &_BeamBandwidthTracerDataRoot, "InternalPositionY", QString::number(this->position->coords().y()));
        }
       
        element->appendChild(_BeamBandwidthTracerDataRoot);

        return _BeamBandwidthTracerDataRoot;
    }

    void BeamBandwidthTracer::readFromProjectFile(QDomElement* element, GraphType type, bool isdiso)
    {
        m_standingWwaveValue = element->elementsByTagName("StandingWwaveValue").item(0).toElement().text().toDouble();
        auto _name = element->elementsByTagName("Name").item(0).toElement().text();
        this->SetName(_name);
        m_curveInfoID = element->elementsByTagName("CurveInfoID").item(0).toElement().text().toInt();
        auto _info = WindowTotalDataInstance->getInfomationCurve2DBasicalByID(m_curveInfoID);
        auto _InternalGraphName = element->elementsByTagName("InternalGraphName").item(0).toElement().text();
        if (type == GraphType::TwoDLineChart)
        {
            QCPGraph* graph = qobject_cast<QCPGraph*>(_info->getCurveLineAddress());
            this->SetLayerable(graph);
            qobject_cast<QCPGraph*>(this->GetLayerable())->setName(_InternalGraphName);
        }
        else if (type == GraphType::PolarGraph)
        {
            QCPPolarGraph* graph = qobject_cast<QCPPolarGraph*>(_info->getCurveLineAddress());
            this->SetLayerable(graph);
            qobject_cast<QCPPolarGraph*>(this->GetLayerable())->setName(_InternalGraphName);
        }      
        if (_name == "半功率波束带宽" || _name == "驻波带宽")
        {
            auto indeicator = qobject_cast<BeamBandwidthTracer*>(this)->GetIndicator();
            auto _InternalindeicatorStartX = element->elementsByTagName("InternalindeicatorStartX").item(0).toElement().text().toDouble();
            auto _InternalindeicatorEndX = element->elementsByTagName("InternalindeicatorEndX").item(0).toElement().text().toDouble();
            indeicator->start->setCoords(_InternalindeicatorStartX, 0);
            indeicator->end->setCoords(_InternalindeicatorEndX, 0);
        }
        else
        {
            auto _InternalPositionY = element->elementsByTagName("InternalPositionY").item(0).toElement().text().toDouble();
            this->position->setCoords(0, _InternalPositionY);
        }
    }

    void BeamBandwidthTracer::slot_selectChange(bool selected)
    {
        this->blockSignals(true);
        m_label->blockSignals(true);
        m_arrow->blockSignals(true);
        m_indicator->blockSignals(true);
        this->setSelected(selected);
        m_label->setSelected(selected);
        m_arrow->setSelected(selected);
        m_indicator->setSelected(selected);
        this->blockSignals(false);
        m_label->blockSignals(false);
        m_arrow->blockSignals(false);
        m_indicator->blockSignals(false);
    }

#if 0
    void BeamBandwidthTracer::draw(QCPPainter* painter)
    {
        if (m_polarGraph)
        {
            updatePositionOnPolar();
            QCPRange range = m_polarGraph->valueAxis()->range();
            double key, value;
            m_polarGraph->pixelsToCoords(m_indicator->start->pixelPosition(), key, value);
            QPointF startCoord(key, value);

            m_polarGraph->pixelsToCoords(m_indicator->end->pixelPosition(), key, value);
            QPointF endCoord(key, value);

            if (startCoord.y() < range.lower || startCoord.y() > range.upper 
                || endCoord.y() < range.lower || endCoord.y() > range.upper)
            {
                if (m_showLabelAndArrow)
                {
                    m_label->setVisible(false);
                    m_arrow->setVisible(false);
                    m_indicator->setVisible(false);
                }
                return;
            }
            else
            {
                if (m_showLabelAndArrow)
                {
                    m_label->setVisible(true);
                    m_arrow->setVisible(true);
                    m_indicator->setVisible(true);
                }
            }
        }
        QCPItemTracer::draw(painter);
    }
#endif

    TracerTableWidget::TracerTableWidget(QCustomPlot* parent) : QTableWidget(parent)
    {
        this->setEditTriggers(NoEditTriggers);
        this->setSelectionMode(ExtendedSelection);
        this->setSelectionBehavior(SelectRows);
        this->setColumnCount(4);
        this->verticalHeader()->hide();
        this->setHorizontalHeaderItem(0, new QTableWidgetItem("名称"));
        this->setHorizontalHeaderItem(1, new QTableWidgetItem("x"));
        this->setHorizontalHeaderItem(2, new QTableWidgetItem("y"));
        this->setHorizontalHeaderItem(3, new QTableWidgetItem("值"));
        HideValueProperty();
        this->hide();
        connect(this->selectionModel(), &QItemSelectionModel::selectionChanged, [this](const QItemSelection& selected, const QItemSelection& deselected)
                {
            for (const auto& index : selected.indexes()) {
                auto item = this->itemFromIndex(index);
                if (item->column() > 0) {
                    continue;
                }
                auto tracer = item->data(QVariant::UserType).value< LineChartTracer* >();
                tracer->setSelected(true);
            }
            for (const auto& index : deselected.indexes()) {
                auto item = this->itemFromIndex(index);
                if (item->column() > 0) {
                    continue;
                }
                auto tracer = item->data(QVariant::UserType).value< LineChartTracer* >();
                tracer->setSelected(false);
            }
            auto parentPlot = qobject_cast<QCustomPlot*>(this->parent());
            parentPlot->replot(); });
        connect(this, &QListView::doubleClicked, [this](const QModelIndex& index)
                {
            auto item = this->itemFromIndex(index);
            auto tracer = item->data(QVariant::UserType).value< LineChartTracer* >();
            if (tracer != nullptr) {
                emit IWidgetSignalInstance->signal_exitAddMarkerState();
                emit signal_doubleClicked(tracer);
            } });
        this->setContextMenuPolicy(Qt::CustomContextMenu);
        m_contextMenu = new QMenu(this);
        auto action1 = m_contextMenu->addAction("退出标记模式");
        auto action2 = m_contextMenu->addAction("删除选中标记");
        auto action3 = m_contextMenu->addAction("删除所有标记");
        auto action = m_contextMenu->addAction("导出标记数据");
        
        connect(action1, &QAction::triggered, this, [this, action1]()
            { 
                if (m_isShowPreviewTracer) {
                    action1->setText("添加标记模式");
                    m_isShowPreviewTracer = false;
                    emit signal_disableTracer();
                }
                else {
                    action1->setText("退出标记模式");
                    m_isShowPreviewTracer = true;
                    emit signal_enableTracer();
                }
            });
        connect(action2, &QAction::triggered, this, &TracerTableWidget::signal_removeMarkerSelect);
        connect(action3, &QAction::triggered, this, &TracerTableWidget::signal_removeMarkerAll);
            
        connect(action, &QAction::triggered, this, &TracerTableWidget::exportDatas);
        connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
        IdaWidgetHelperInstance->setTableWidgetStyle(this);
        InternalWindowFrameless* dialog = new InternalWindowFrameless(this);
        // this->horizontalHeader()->viewport()->installEventFilter(this);
    }

    void TracerTableWidget::AppendTracerProperty(LineChartTracer* tracer)
    {
        this->insertRow(this->rowCount());
        auto nameItem = new QTableWidgetItem(tracer->GetName());
        nameItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
        this->setItem(this->rowCount() - 1, 0, nameItem);
        auto xItem = new QTableWidgetItem(QString::number(tracer->position->coords().x()));
        xItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
        this->setItem(this->rowCount() - 1, 1, xItem);
        auto yItem = new QTableWidgetItem(QString::number(tracer->position->coords().y()));
        yItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
        this->setItem(this->rowCount() - 1, 2, yItem);
        auto valueItem = new QTableWidgetItem(QString::number(tracer->GetValue()));
        valueItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
        this->setItem(this->rowCount() - 1, 3, valueItem);
    }

    void TracerTableWidget::slot_updateTracerProperty()
    {
        //if (this->isHidden())
        //{
        //    return;
        //}
        bool hasVisibleRow = false;
        for (int i = 0; i < this->rowCount(); ++i)
        {
            auto tracer = this->item(i, 0)->data(QVariant::UserType).value<LineChartTracer*>();
            if (tracer->visible())
            {
                this->item(i, 0)->setText(tracer->GetName());
                this->item(i, 1)->setText(QString::number(tracer->position->coords().x()));
                this->item(i, 2)->setText(QString::number(tracer->position->coords().y()));
                this->item(i, 3)->setText(QString::number(tracer->GetValue()));
                this->showRow(i);
                hasVisibleRow = true;

                auto property = tracer->getStyle2DTracerProperty();
                property->m_x = tracer->position->coords().x();
                property->m_y = tracer->position->coords().y();
            }
            else
            {
                this->hideRow(i);
            }
        }
        hasVisibleRow ? this->show() : this->hide();
    }

    void TracerTableWidget::slot_updateTracerChange()
    {
        if (this->isHidden())
        {
            return;
        }
        this->selectionModel()->blockSignals(true);
        this->selectionModel()->clearSelection();
        for (int i = 0; i < this->rowCount(); ++i)
        {
            auto tracer = this->item(i, 0)->data(QVariant::UserType).value<LineChartTracer*>();
            if (tracer->visible())
            {
                if (tracer->selected())
                {
                    this->selectRow(i);
                }
            }
        }
        this->selectionModel()->blockSignals(false);
    }

    void TracerTableWidget::contextMenuRequest(QPoint pos)
    {
        m_contextMenu->popup(this->mapToGlobal(pos));
    }

    QString TracerTableWidget::exportDatas()
    {
        emit IWidgetSignalInstance->signal_exitAddMarkerState();
        QVector<QStringList> datas;
        for (int i = 0; i < this->rowCount(); ++i)
        {
            if (isRowHidden(i))
            {
                continue;
            }
            QStringList dataList;
            for (int j = 0; j < this->columnCount(); ++j)
            {
                if (isColumnHidden(j))
                {
                    continue;
                }
                if (datas.isEmpty() && i == 0)
                {
                    dataList.append(this->horizontalHeaderItem(j)->text());
                }
                else
                {
                    dataList.append(this->item(i, j)->text());
                }
            }
            if (datas.isEmpty() && i == 0)
            {
                --i;
            }
            datas.append(dataList);
        }

        QString fileName;
        if (m_fileName.isEmpty())
        {
            // 初步写入数据到txt文件
            fileName = QFileDialog::getSaveFileName(this, tr("导出Marker数据"), "",                  // 默认文件名
                tr("csv 文件 (*.csv);;txt 文件 (*.txt)")); // 文件过滤器
        }
        else
        {
            fileName = m_fileName;
            m_fileName = QString();
        }

        if (fileName.isEmpty())
        {
            return fileName;
        }

        QFile file(fileName);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            // 写入 BOM，如果需要 Excel 正确识别 UTF-8 BOM
            file.write("\xEF\xBB\xBF");
            for (int i = 0; i < datas.size(); ++i)
            {
                if (i == 0)
                {
                    file.write("#");
                }
                file.write(datas.at(i).join(" , ").toUtf8() + "\n");
            }
            file.close();
        }

        emit IWidgetSignalInstance->signal_exitAddMarkerState();
        return fileName;
    }

    void TracerTableWidget::setFileName(QString fileName)
    {
        m_fileName = fileName;
    }

    QDomElement& TracerTableWidget::writeToProjectFile(QDomDocument* doc, QDomElement* element, GraphType graphType, bool isdiso)
    {
        QDomElement _TracerTableWidgetDataRoot = doc->createElement("TracerTableWidget");
        QDomAttr idattr = doc->createAttribute("ID");
        idattr.setValue(QString::number(1));
        _TracerTableWidgetDataRoot.setAttributeNode(idattr);

        for (int i = 0; i < this->rowCount(); ++i)
        {
            auto tracer = this->item(i, 0)->data(QVariant::UserType).value<LineChartTracer*>();
            tracer->writeToProjectFile(doc, &_TracerTableWidgetDataRoot, graphType, isdiso);
        }

        element->appendChild(_TracerTableWidgetDataRoot);

        return _TracerTableWidgetDataRoot;
    }

    void TracerTableWidget::readFromProjectFile(QDomNodeList* nodelist, QCustomPlot* customPlot, GraphType graphType, bool isdiso)
    {
        auto _element = nodelist->at(0).toElement();
        auto _nodelist = _element.elementsByTagName("LineChartTracer");
        auto _tracerCount = _nodelist.count();
        for (int i = 0; i < _tracerCount; ++i)
        {
            auto _tracerElement = _nodelist.at(i).toElement();
            auto tracer = new LineChartTracer(customPlot);
            tracer->readFromProjectFile(&_tracerElement, graphType, isdiso);  
            tracer->setGraphKey(tracer->position->coords().x());
            auto _info = WindowTotalDataInstance->getInfomationCurve2DBasicalByID(tracer->getCurveInfoID());
            QCPGraph* graph = qobject_cast<QCPGraph*>(_info->getCurveLineAddress());
            tracer->setGraph(graph);

            this->AppendTracerProperty(tracer);
            auto tmpProperty = tracer->getStyle2DTracerProperty();
            if (tmpProperty == nullptr)
                return;
            tracer->SetName(tmpProperty->m_tracerName);
            tracer->setGraphKey(tmpProperty->m_x);
            tracer->setStyle(QCPItemTracer::TracerStyle(tmpProperty->m_symbolStyle + 1));
            tracer->setSize(tmpProperty->m_symbolSize * 2);
            tracer->setPen(QPen(tmpProperty->m_symbolColor));
        }

    }

    // bool TracerTableWidget::eventFilter(QObject* obj, QEvent* event)
    //{
    //     switch (event->type())
    //     {
    //     case QEvent::MouseMove:
    //     case QEvent::HoverMove:
    //     case QEvent::MouseButtonPress:
    //     case QEvent::MouseButtonRelease:
    //     case QEvent::MouseButtonDblClick:
    //     case QEvent::Leave:
    //     {
    //         event->ignore();
    //         return true;
    //         break;
    //     }

    //    default:
    //        break;
    //    }
    //    return QObject::eventFilter(obj, event);
    //}

    MeasureTableWidget::MeasureTableWidget(QCustomPlot* parent) : QTableWidget(parent)
    {
        this->setEditTriggers(NoEditTriggers);
        this->setSelectionMode(ExtendedSelection);
        this->setSelectionBehavior(SelectRows);
        this->setColumnCount(3);
        this->verticalHeader()->hide();
        this->setHorizontalHeaderItem(0, new QTableWidgetItem("曲线名"));
        this->setHorizontalHeaderItem(1, new QTableWidgetItem("测量参数"));
        this->setHorizontalHeaderItem(2, new QTableWidgetItem("测量值"));
        this->hide();
        connect(this->selectionModel(), &QItemSelectionModel::selectionChanged, [this](const QItemSelection& selected, const QItemSelection& deselected)
                {
            for (const auto& index : selected.indexes()) {
                auto item = this->itemFromIndex(index);
                if (item->column() > 0) {
                    continue;
                }
                auto tracer = item->data(QVariant::UserType).value< LineChartTracer* >();
                tracer->setSelected(true);
            }
            for (const auto& index : deselected.indexes()) {
                auto item = this->itemFromIndex(index);
                if (item->column() > 0) {
                    continue;
                }
                auto tracer = item->data(QVariant::UserType).value< LineChartTracer* >();
                tracer->setSelected(false);
            }
            auto parentPlot = qobject_cast<QCustomPlot*>(this->parent());
            parentPlot->replot(); });
        this->setContextMenuPolicy(Qt::CustomContextMenu);
        m_contextMenu = new QMenu(this);
        auto action = m_contextMenu->addAction("导出标记数据");
        IdaWidgetHelperInstance->setTableWidgetStyle(this);
        connect(action, &QAction::triggered, this, &MeasureTableWidget::exportDatas);
        connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequest(QPoint)));
        InternalWindowFrameless* dialog = new InternalWindowFrameless(this);
        // this->horizontalHeader()->viewport()->installEventFilter(this);
    }

    void MeasureTableWidget::AppendTracerProperty(LineChartTracer* tracer)
    {
        this->insertRow(this->rowCount());
        auto graphNameItem = new QTableWidgetItem(qobject_cast<QCPGraph*>(tracer->GetLayerable())->name());
        graphNameItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
        this->setItem(this->rowCount() - 1, 0, graphNameItem);
        auto nameItem = new QTableWidgetItem(tracer->GetName());
        nameItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
        this->setItem(this->rowCount() - 1, 1, nameItem);
        if (tracer->GetName() == "半功率波束带宽" || tracer->GetName() == "驻波带宽")
        {
            auto indeicator = qobject_cast<BeamBandwidthTracer*>(tracer)->GetIndicator();
            double difference = std::abs(indeicator->start->coords().x() - indeicator->end->coords().x());
            auto differenceItem = new QTableWidgetItem(QString::number(difference));
            differenceItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
            this->setItem(this->rowCount() - 1, 2, differenceItem);
        }
        else
        {
            auto yItem = new QTableWidgetItem(QString::number(tracer->position->coords().y()));
            yItem->setData(QVariant::UserType, QVariant::fromValue(tracer));
            this->setItem(this->rowCount() - 1, 2, yItem);
        }
    }

    void MeasureTableWidget::slot_updateTracerProperty()
    {
        //if (this->isHidden())
        //{
        //    return;
        //}
        bool hasVisibleRow = false;
        for (int i = 0; i < this->rowCount(); ++i)
        {
            auto tracer = this->item(i, 0)->data(QVariant::UserType).value<LineChartTracer*>();
            auto graph = qobject_cast<QCPGraph*>(tracer->GetLayerable());
            if (graph == nullptr)
            {
                continue;
            }
            const auto& graphData = graph->data();
            bool findRange = false;
            auto range = graphData->valueRange(findRange);
            double key = 0;
            double value = 0;
            if (!findRange)
            {
                tracer->setVisible(false);
                this->hideRow(i);
                continue;
            }
            if (tracer->GetName() == "半功率波束带宽" || tracer->GetName() == "驻波带宽")
            {
                // tracer->setVisible(graph->visible());
                if (!tracer->visible())
                {
                    //this->hideRow(i);
                    //continue;
                }
                auto indeicator = qobject_cast<BeamBandwidthTracer*>(tracer)->GetIndicator();
                double difference = std::abs(indeicator->start->coords().x() - indeicator->end->coords().x());
                QString tracerYStr{};
                if (!tracer->getMeasurementConditionsIsSatisfied())
                    tracerYStr = QStringLiteral("不满足测量条件");
                else
                    tracerYStr = QString::number(difference);
                this->item(i, 2)->setText(tracerYStr);
            }
            else
            {
                if (tracer->GetName() == "最大值")
                {
                    tracer->setVisible(graph->visible());
                    if (!tracer->visible())
                    {
                        //this->hideRow(i);
                        //continue;
                    }
                    value = range.upper;
                    for (auto iter = graphData->begin(); iter != graphData->end(); ++iter)
                    {
                        if (iter->value == value)
                        {
                            key = iter->key;
                            break;
                        }
                    }
                }
                else if (tracer->GetName() == "最小值")
                {
                    tracer->setVisible(graph->visible());
                    if (!tracer->visible())
                    {
                        //this->hideRow(i);
                        //continue;
                    }
                    value = range.lower;
                    for (auto iter = graphData->begin(); iter != graphData->end(); ++iter)
                    {
                        if (iter->value == value)
                        {
                            key = iter->key;
                            break;
                        }
                    }
                }
                else if (tracer->GetName() == "平均值")
                {
                    int num = 0;
                    for (auto iter = graphData->begin(); iter != graphData->end(); ++iter)
                    {
                        ++num;
                        value += iter->value;
                    }
                    value /= num;
                }
                tracer->position->setCoords(key, value);
                QString tracerYStr{};
                if (!tracer->getMeasurementConditionsIsSatisfied())
                    tracerYStr = QStringLiteral("不满足测量条件");
                else
                    tracerYStr = QString::number(tracer->position->coords().y());
                this->item(i, 2)->setText(tracerYStr);
            }
            this->item(i, 0)->setText(graph->name());
            this->item(i, 1)->setText(tracer->GetName());
            //if (tracer->visible())
            if (graph->visible())
            {
                hasVisibleRow = true;
                this->showRow(i);
            }
            else
            {
                 this->hideRow(i);
            }
                //if (tracer->GetName() != "平均值")
                //{
                //    this->removeRow(i);
                //}
        }

        hasVisibleRow ? this->show() : this->hide();
    }

    void MeasureTableWidget::slot_updateTracerChange()
    {
        if (this->isHidden())
        {
            return;
        }
        this->selectionModel()->blockSignals(true);
        this->selectionModel()->clearSelection();
        for (int i = 0; i < this->rowCount(); ++i)
        {
            auto tracer = this->item(i, 0)->data(QVariant::UserType).value<LineChartTracer*>();
            if (tracer->visible())
            {
                if (tracer->selected())
                {
                    this->selectRow(i);
                }
            }
        }
        this->selectionModel()->blockSignals(false);
    }

    void MeasureTableWidget::contextMenuRequest(QPoint pos)
    {
        m_contextMenu->popup(this->mapToGlobal(pos));
    }

    void MeasureTableWidget::exportDatas()
    {
        QVector<QStringList> datas;
        for (int i = 0; i < this->rowCount(); ++i)
        {
            if (isRowHidden(i))
            {
                continue;
            }
            QStringList dataList;
            for (int j = 0; j < this->columnCount(); ++j)
            {
                if (isColumnHidden(j))
                {
                    continue;
                }
                if (datas.isEmpty() && i == 0)
                {
                    dataList.append(this->horizontalHeaderItem(j)->text());
                }
                else
                {
                    dataList.append(this->item(i, j)->text());
                }
            }
            if (datas.isEmpty() && i == 0)
            {
                --i;
            }
            datas.append(dataList);
        }

        // 初步写入数据到txt文件
        QString fileName = QFileDialog::getSaveFileName(this, tr("导出Marker数据"), "",                  // 默认文件名
                                                        tr("csv 文件 (*.csv);;txt 文件 (*.txt)")); // 文件过滤器

        if (fileName.isEmpty())
        {
            return;
        }

        QFile file(fileName);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            // 写入 BOM，如果需要 Excel 正确识别 UTF-8 BOM
            file.write("\xEF\xBB\xBF");
            for (int i = 0; i < datas.size(); ++i)
            {
                if (i == 0)
                {
                    file.write("#");
                }
                file.write(datas.at(i).join(" , ").toUtf8() + "\n");
            }
            file.close();
        }
    }

    QDomElement& MeasureTableWidget::writeToProjectFile(QDomDocument* doc, QDomElement* element, bool isdiso)
    {
        QDomElement _MeasureTableWidgetDataRoot = doc->createElement("MeasureTableWidget");
        QDomAttr idattr = doc->createAttribute("ID");
        idattr.setValue(QString::number(1));
        _MeasureTableWidgetDataRoot.setAttributeNode(idattr);

        for (int i = 0; i < this->rowCount(); ++i)
        {
            auto tracer = this->item(i, 0)->data(QVariant::UserType).value<LineChartTracer*>();
            tracer->writeToProjectFile(doc, &_MeasureTableWidgetDataRoot, GraphType::TwoDLineChart, isdiso);
        }

        element->appendChild(_MeasureTableWidgetDataRoot);

        return _MeasureTableWidgetDataRoot;
    }

    void MeasureTableWidget::readFromProjectFile(QDomNodeList* nodelist, QCustomPlot* customPlot, bool isdiso)
    {
        auto _element = nodelist->at(0).toElement();
        auto _nodelist = _element.elementsByTagName("LineChartTracer");
        auto _tracerCount = _nodelist.count();
        for (int i = 0; i < _tracerCount; ++i)
        {
            auto _tracerElement = _nodelist.at(i).toElement();
            auto _TracerType = _tracerElement.attribute("TracerType");
            LineChartTracer* tracer = nullptr;
            if (_TracerType == "BeamBandwidth")
            {
                tracer = new BeamBandwidthTracer(customPlot);
            }
            else
            {
                tracer = new LineChartTracer(customPlot);
            }
            tracer->readFromProjectFile(&_tracerElement, GraphType::TwoDLineChart, isdiso);
            this->AppendTracerProperty(tracer);
        }

    }

    // bool MeasureTableWidget::eventFilter(QObject* obj, QEvent* event)
    //{
    //     switch (event->type())
    //     {
    //     case QEvent::MouseMove:
    //     case QEvent::HoverMove:
    //     case QEvent::MouseButtonPress:
    //     case QEvent::MouseButtonRelease:
    //     case QEvent::MouseButtonDblClick:
    //     case QEvent::Leave:
    //     {
    //         event->ignore();
    //         return true;
    //         break;
    //     }

    //    default:
    //        break;
    //    }
    //    return QObject::eventFilter(obj, event);
    //}
} // namespace pst
